import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.NinePatch
import android.graphics.Rect
import android.graphics.drawable.NinePatchDrawable
import android.os.Handler
import android.os.Looper
import android.util.AttributeSet
import android.util.Log
import android.util.LruCache
import android.widget.FrameLayout
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.File
import java.io.IOException

class NinePatchFrameLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
    companion object {
        private val memoryCache = object : LruCache<String, NinePatchDrawable>(10) {} // 缓存最多 10 张图
    }
    private val client = OkHttpClient()
    private var currentCall: Call? = null

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        currentCall?.cancel()
    }
    fun setNinePatchUrl(url: String, onLoaded: (() -> Unit)? = null) {
        memoryCache.get(url)?.let {
            background = it
            onLoaded?.invoke()
            return
        }

        val cacheFile = getCacheFile(url)
        if (cacheFile.exists()) {
            tryLoadFromFile(cacheFile, onLoaded, url)
        } else {
            downloadAndCache(url, cacheFile, onLoaded)
        }
    }

    fun setNinePatchAsset(assetPath: String, onLoaded: (() -> Unit)? = null) {
        memoryCache.get(assetPath)?.let {
            background = it
            onLoaded?.invoke()
            return
        }

        try {
            val am = context.assets
            val inputStream = am.open("flutter_assets/$assetPath")
            val bytes = inputStream.readBytes()
            inputStream.close()

            val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
            val chunk = bitmap.ninePatchChunk
            if (NinePatch.isNinePatchChunk(chunk)) {
                val drawable = NinePatchDrawable(resources, bitmap, chunk, Rect(), null)
                memoryCache.put(assetPath, drawable) // ✅ 存入内存缓存
                Handler(Looper.getMainLooper()).post {
                    background = drawable
                    onLoaded?.invoke()
                }
            } else {
                Log.w("NinePatchFrameLayout", "Asset 文件不是合法的 .9.png: $assetPath")
            }
        } catch (e: Exception) {
            Log.e("NinePatchFrameLayout", "加载 Asset 失败: $assetPath", e)
        }
    }

    private fun tryLoadFromFile(file: File, onLoaded: (() -> Unit)? = null, cacheKey: String? = null) {
        val bitmap = BitmapFactory.decodeFile(file.absolutePath)
        val chunk = bitmap.ninePatchChunk
        if (NinePatch.isNinePatchChunk(chunk)) {
            val drawable = NinePatchDrawable(resources, bitmap, chunk, Rect(), null)
            if (cacheKey != null) {
                memoryCache.put(cacheKey, drawable) // ✅ 存入内存缓存
            }
            Handler(Looper.getMainLooper()).post {
                background = drawable
                onLoaded?.invoke()
            }
        } else {
            file.delete()
        }
    }

    private fun downloadAndCache(url: String, cacheFile: File, onLoaded: (() -> Unit)? = null) {
        val request = Request.Builder().url(url).build()
        val call = client.newCall(request)
        currentCall = call
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                Log.e("NinePatchFrameLayout", "下载失败: ${e.message}")
            }

            override fun onResponse(call: Call, response: Response) {
                if (!call.isCanceled) {
                    val body = response.body() ?: return
                    val bytes = body.bytes()
                    cacheFile.writeBytes(bytes)
                    tryLoadFromFile(cacheFile, onLoaded)
                }
            }
        })
    }

    /**
     * 根据 URL 生成唯一的缓存文件路径
     */
    private fun getCacheFile(url: String): File {
        val fileName = url.hashCode().toString() + ".9.png"
        val cacheDir = File(context.filesDir, "ninepatch_cache")
        if (!cacheDir.exists()) cacheDir.mkdirs()
        return File(cacheDir, fileName)
    }
}
